package org.ohos.rajawali3d.examples.examples.ui;

import ohos.agp.render.BlendMode;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.Texture;
import ohos.agp.utils.Color;
import ohos.app.Context;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;
import ohos.opengl.Bitmap;
import org.ohos.rajawali3d.examples.examples.AExampleFragment;
import org.rajawali3d.animation.Animation;
import org.rajawali3d.animation.RotateOnAxisAnimation;
import org.rajawali3d.lights.DirectionalLight;
import org.rajawali3d.materials.Material;
import org.rajawali3d.materials.methods.DiffuseMethod;
import org.rajawali3d.materials.textures.ATexture;
import org.rajawali3d.materials.textures.AlphaMapTexture;
import org.rajawali3d.math.vector.Vector3;
import org.rajawali3d.primitives.Sphere;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class CanvasTextFragment extends AExampleFragment {

    @Override
    public AExampleRenderer createRenderer() {
        return new CanvasTextRenderer(getContext(), this);
    }

    public static final class CanvasTextRenderer extends AExampleRenderer {
        private AlphaMapTexture mTimeTexture;
        private PixelMap mTimeBitmap;
        private Canvas mTimeCanvas;
        private Paint mTextPaint;
        private SimpleDateFormat mDateFormat;
        private int mFrameCount;
        private boolean mShouldUpdateTexture;

        public CanvasTextRenderer(Context context, AExampleFragment fragment) {
            super(context, fragment);
        }

        @Override
        public void initScene() {
            DirectionalLight light = new DirectionalLight(.1f, .1f, -1);
            light.setPower(2);
            getCurrentScene().addLight(light);

            Material timeSphereMaterial = new Material();
            timeSphereMaterial.enableLighting(true);
            timeSphereMaterial.setDiffuseMethod(new DiffuseMethod.Lambert());
            mTimeBitmap = Bitmap.create(256, 256, PixelFormat.ARGB_8888);
            mTimeTexture = new AlphaMapTexture("timeTexture", mTimeBitmap);
            try {
                timeSphereMaterial.addTexture(mTimeTexture);
            } catch (ATexture.TextureException e) {
                e.printStackTrace();
            }
            timeSphereMaterial.setColorInfluence(1);

            Sphere parentSphere = null;

            for (int i = 0; i < 20; i++) {
                Sphere timeSphere = new Sphere(.6f, 12, 12);
                timeSphere.setMaterial(timeSphereMaterial);
                timeSphere.setDoubleSided(true);
                timeSphere.setColor((int) (Math.random() * 0xffffff));

                if (parentSphere == null) {
                    timeSphere.setPosition(0, 0, -3);
                    timeSphere.setRenderChildrenAsBatch(true);
                    getCurrentScene().addChild(timeSphere);
                    parentSphere = timeSphere;
                } else {
                    timeSphere.setX(-3 + (float) (Math.random() * 6));
                    timeSphere.setY(-3 + (float) (Math.random() * 6));
                    timeSphere.setZ(-3 + (float) (Math.random() * 6));
                    parentSphere.addChild(timeSphere);
                }

                int direction = Math.random() < .5 ? 1 : -1;

                RotateOnAxisAnimation anim = new RotateOnAxisAnimation(Vector3.Axis.Y, 0,
                        360 * direction);
                anim.setRepeatMode(Animation.RepeatMode.INFINITE);
                anim.setDurationMilliseconds(i == 0 ? 12000
                        : 4000 + (int) (Math.random() * 4000));
                anim.setTransformable3D(timeSphere);
                getCurrentScene().registerAnimation(anim);
                anim.play();
            }
        }

        public void updateTimeBitmap() {
            new Thread(new Runnable() {
                public void run() {
                    if (mTimeCanvas == null) {

                        mTimeCanvas = new Canvas(new Texture(mTimeBitmap));
                        mTextPaint = new Paint();
                        mTextPaint.setAntiAlias(true);
                        mTextPaint.setColor(Color.WHITE);
                        mTextPaint.setTextSize(35);
                        mDateFormat = new SimpleDateFormat("HH:mm:ss",
                                Locale.ENGLISH);
                    }
                    //
                    // -- Clear the canvas, transparent
                    //
                    mTimeCanvas.drawColor(0, BlendMode.CLEAR);
                    //
                    // -- Draw the time on the canvas
                    //
                    mTimeCanvas.drawText(mTextPaint, mDateFormat.format(new Date()), 75, 128);
                    //
                    // -- Indicates that the texture should be updated on the OpenGL thread.
                    //
                    mShouldUpdateTexture = true;
                }
            }).start();
        }

        @Override
        protected void onRender(long elapsedRealtime, double deltaTime) {
            //
            // -- not a really accurate way of doing things but you get the point :)
            //
            if (mFrameCount++ >= mFrameRate) {
                mFrameCount = 0;
                updateTimeBitmap();
            }
            //
            // -- update the texture because it is ready
            //
            if (mShouldUpdateTexture) {
                mTimeTexture.setBitmap(mTimeBitmap);
                mTextureManager.replaceTexture(mTimeTexture);
                mShouldUpdateTexture = false;
            }
            super.onRender(elapsedRealtime, deltaTime);
        }

    }

}
